'''
项目名称：产业园区管理运营平台
文件名称：财务与账单数据生成脚本
@Author: 王旭
@Contact: 1643959780@qq.com
@Created: 2025/06/28
@Version: V1.0

@Description:
本脚本用于为产业园区管理运营平台生成财务相关的账单数据。
这是数据初始化的最后一步，它依赖于之前所有脚本生成的数据。
主要功能包括：
1. 基于合同生成周期性的费用账单（如租金、物业费、停车费）。
2. 基于已完成的服务生成一次性的费用账单（如维修费、保洁费、水费）。
3. 确保账单与合同/服务记录正确关联。

@Modifications:
- V1.0 (2025/06/28): 初始版本，实现账单数据的生成。
'''

import os
import sys
import django
import random
import datetime
from django.utils import timezone
from dateutil.relativedelta import relativedelta

# --- Start: 动态添加项目根目录到 sys.path ---
current_script_path = os.path.abspath(__file__)
script_dir = os.path.dirname(current_script_path)
project_root = os.path.dirname(script_dir)
sys.path.append(project_root)
# --- End: 动态添加项目根目录到 sys.path ---

# 设置Django环境
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'smartpark.settings')
django.setup()

# 导入模型
from django.db import transaction
from users.models import User, Company
from services.models import (
    Contract, WaterDeliveryService, TemporaryParkingService,
    RepairService, CleaningBookingService
)
from finance.models import Bill

def clear_old_finance_data():
    """清除旧的账单数据及服务关联"""
    print("--- 正在清除旧的财务账单数据... ---")
    # 先解除服务表与账单的关联
    WaterDeliveryService.objects.update(bill_id=None)
    TemporaryParkingService.objects.update(bill_id=None)
    RepairService.objects.update(bill_id=None)
    CleaningBookingService.objects.update(bill_id=None)
    
    # 然后删除所有账单
    Bill.objects.all().delete()
    print("旧账单数据已清除，相关服务的账单关联已重置。")

@transaction.atomic
def create_finance_data():
    """创建所有账单数据"""
    print("--- 开始创建财务与账单数据 ---")

    try:
        create_bills_from_contracts()
        create_bills_from_services()

        print("\n财务与账单数据生成完成！")
        # print_statistics()
    except Exception as e:
        print(f"\n!!! 数据生成过程中发生错误，事务将回滚 !!!")
        print(f"错误详情: {e}")
        import traceback
        traceback.print_exc()

def create_bills_from_contracts():
    """根据合同生成账单"""
    print("\n根据合同生成账单...")
    contracts = Contract.objects.filter(status='生效中')
    created_count = 0

    for contract in contracts:
        # 确保合同有支付方
        if not contract.user and not contract.company:
            print(f"警告: 合同 {contract.contract_id} 没有支付方，跳过账单生成")
            continue
            
        # 计算每期支付金额
        cycle_months = {'月付': 1, '季付': 3, '年付': 12}.get(contract.payment_cycle, 12)
        total_months = (contract.end_date.year - contract.start_date.year) * 12 + contract.end_date.month - contract.start_date.month
        num_installments = (total_months + cycle_months - 1) // cycle_months
        amount_per_installment = contract.contract_amount / num_installments if num_installments > 0 else 0

        if amount_per_installment == 0:
            continue
            
        # 无论是房源还是车位，长期合同产生的都是'租金'
        bill_type = '租金'

        # 为每个合同生成1到5期账单
        for i in range(random.randint(1, 5)):
            bill_date = contract.start_date + relativedelta(months=i * cycle_months)
            if bill_date > contract.end_date:
                break
                
            due_date = bill_date + relativedelta(days=10)
            now = timezone.now().date()
            
            payment_status = '未支付'
            payment_date = None
            if due_date < now:
                payment_status = random.choices(['已支付', '逾期'], weights=[8, 2])[0]
                if payment_status == '已支付':
                    payment_date = due_date - relativedelta(days=random.randint(1, 5))
            
            bill = Bill.objects.create(
                bill_number=f"BILL-CT-{contract.contract_id}-{bill_date.strftime('%Y%m%d')}",
                payer_user=contract.user,
                payer_company=contract.company,
                amount=round(amount_per_installment, 2),
                due_date=due_date,
                payment_date=payment_date,
                payment_status=payment_status,
                bill_type=bill_type,
                bill_period=bill_date.strftime('%Y-%m'),
                contract=contract,
                remarks=f"来源合同: {contract.contract_number}",
                created_at=timezone.now(),
                updated_at=timezone.now()
            )
            created_count += 1
    print(f"成功从合同生成 {created_count} 条租金账单。")

def create_bills_from_services():
    """根据已完成的增值服务生成账单"""
    print("\n根据增值服务生成账单...")
    total_created_count = 0
    
    # 1. 从送水服务生成账单
    water_services = WaterDeliveryService.objects.filter(
        status__in=['已送达', '已评价'], 
        total_amount__gt=0, 
        bill_id__isnull=True
    ).select_related('applicant_user')
    
    count = 0
    for service in water_services:
        if not service.applicant_user:
            print(f"警告: 送水服务 {service.service_id} 没有申请用户，跳过账单生成")
            continue
            
        bill = Bill.objects.create(
            bill_number=f"BILL-SV-WA-{service.service_id}",
            payer_user=service.applicant_user,
            payer_company=None,  # 送水服务通常是个人支付
            amount=service.total_amount,
            due_date=timezone.now().date() + relativedelta(days=7),
            payment_status='未支付',
            bill_type='水费',
            bill_period=timezone.now().strftime('%Y-%m'),
            service_id=service.service_id,
            remarks=f"来源服务: 送水服务 - ID: {service.service_id}",
            created_at=timezone.now(),
            updated_at=timezone.now()
        )
        
        # 回写bill_id到服务表
        service.bill = bill
        service.save()
        count += 1
        
    print(f"成功从送水服务生成 {count} 条账单。")
    total_created_count += count
    
    # 2. 从临时停车记录生成账单
    parking_services = TemporaryParkingService.objects.filter(
        payable_amount__gt=0, 
        exit_time__isnull=False,
        bill_id__isnull=True
    ).select_related('user')
    
    count = 0
    for service in parking_services:
        if not service.user:
            print(f"警告: 临时停车记录 {service.parking_record_id} 没有关联用户，跳过账单生成")
            continue
            
        due_date = service.exit_time.date() + relativedelta(days=1)
        now = timezone.now().date()
        
        # 模拟支付状态
        payment_status = '未支付'
        payment_date = None
        if due_date < now:  # 如果是过去的账单
            if random.random() < 0.8:  # 80%的几率已支付
                payment_status = '已支付'
                payment_date = due_date - relativedelta(days=random.randint(0, 1))
            else:
                payment_status = '逾期'
        
        bill = Bill.objects.create(
            bill_number=f"BILL-PK-{service.parking_record_id}-{random.randint(100,999)}",
            payer_user=service.user,
            payer_company=None,  # 临停通常是个人行为
            amount=service.payable_amount,
            due_date=due_date,
            payment_date=payment_date,
            payment_status=payment_status,
            bill_type='停车费',
            bill_period=service.entry_time.strftime('%Y-%m'),
            remarks=f"来源服务: 临时停车 - 车牌: {service.plate_number}",
            created_at=timezone.now(),
            updated_at=timezone.now()
        )
        
        # 回写bill_id到服务表
        service.bill = bill
        service.save()
        count += 1
    
    print(f"成功从临时停车服务生成 {count} 条账单。")
    total_created_count += count
    
    # 3. 从维修服务生成账单（只针对有费用且已完成的维修）
    repair_services = RepairService.objects.filter(
        status__in=['已完成', '已评价'],
        repair_cost__gt=0,
        bill_id__isnull=True
    ).select_related('applicant_user')
    
    count = 0
    for service in repair_services:
        if not service.applicant_user:
            print(f"警告: 维修服务 {service.repair_id} 没有申请用户，跳过账单生成")
            continue
            
        bill = Bill.objects.create(
            bill_number=f"BILL-SV-RP-{service.repair_id}",
            payer_user=service.applicant_user,
            payer_company=None,  # 维修服务通常是个人支付
            amount=service.repair_cost,
            due_date=timezone.now().date() + relativedelta(days=7),
            payment_status='未支付',
            bill_type='维修费',
            bill_period=timezone.now().strftime('%Y-%m'),
            service_id=service.repair_id,
            remarks=f"来源服务: 维修服务 - ID: {service.repair_id}",
            created_at=timezone.now(),
            updated_at=timezone.now()
        )
        
        # 回写bill_id到服务表
        service.bill = bill
        service.save()
        count += 1
        
    print(f"成功从维修服务生成 {count} 条账单。")
    total_created_count += count
    
    # 4. 从保洁服务生成账单（只针对有费用且已完成的保洁）
    cleaning_services = CleaningBookingService.objects.filter(
        status__in=['已完成', '已评价'],
        service_fee__gt=0,
        bill_id__isnull=True
    ).select_related('applicant_user')
    
    count = 0
    for service in cleaning_services:
        if not service.applicant_user:
            print(f"警告: 保洁服务 {service.booking_id} 没有申请用户，跳过账单生成")
            continue
            
        bill = Bill.objects.create(
            bill_number=f"BILL-SV-CL-{service.booking_id}",
            payer_user=service.applicant_user,
            payer_company=None,  # 保洁服务通常是个人支付
            amount=service.service_fee,
            due_date=timezone.now().date() + relativedelta(days=7),
            payment_status='未支付',
            bill_type='保洁费',
            bill_period=timezone.now().strftime('%Y-%m'),
            service_id=service.booking_id,
            remarks=f"来源服务: 保洁服务 - ID: {service.booking_id}",
            created_at=timezone.now(),
            updated_at=timezone.now()
        )
        
        # 回写bill_id到服务表
        service.bill = bill
        service.save()
        count += 1
        
    print(f"成功从保洁服务生成 {count} 条账单。")
    total_created_count += count
    
    print(f"总共从各类服务生成 {total_created_count} 条账单。")

def print_statistics():
    """打印数据统计信息"""
    print("\n=== 财务数据统计 ===")
    total_bills = Bill.objects.count()
    print(f"账单总数: {total_bills}")
    
    bill_types = {}
    for bill in Bill.objects.all():
        bill_types[bill.bill_type] = bill_types.get(bill.bill_type, 0) + 1
    
    print("\n账单类型分布:")
    for b_type, count in bill_types.items():
        print(f"- {b_type}: {count}条")
        
    payment_statuses = {}
    for bill in Bill.objects.all():
        payment_statuses[bill.payment_status] = payment_statuses.get(bill.payment_status, 0) + 1
        
    print("\n支付状态分布:")
    for status, count in payment_statuses.items():
        print(f"- {status}: {count}条")
    
    # 检查是否有没有支付方的账单
    no_payer_bills = Bill.objects.filter(payer_user__isnull=True, payer_company__isnull=True).count()
    if no_payer_bills > 0:
        print(f"\n警告: 发现 {no_payer_bills} 条没有支付方的账单！")
    else:
        print("\n所有账单都有明确的支付方")
    
    # 检查服务关联情况
    water_bills = WaterDeliveryService.objects.filter(bill__isnull=False).count()
    parking_bills = TemporaryParkingService.objects.filter(bill__isnull=False).count()
    repair_bills = RepairService.objects.filter(bill__isnull=False).count()
    cleaning_bills = CleaningBookingService.objects.filter(bill__isnull=False).count()
    
    print("\n服务关联账单情况:")
    print(f"- 送水服务关联账单: {water_bills}条")
    print(f"- 临时停车关联账单: {parking_bills}条")
    print(f"- 维修服务关联账单: {repair_bills}条")
    print(f"- 保洁服务关联账单: {cleaning_bills}条")

if __name__ == "__main__":
    clear_old_finance_data()
    create_finance_data() 